﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace revup
{
    class Program
    {
        static StreamWriter flog;
        static string basePath = AppDomain.CurrentDomain.BaseDirectory;
        static string trash = basePath + "revup.trash\\";
        static bool sessionStarted = false;
        static string[] cmdLine = new string[2];

        static void Main(string[] args)
        {
            flog = new StreamWriter(basePath+"revup.log", true);
            if (!Directory.Exists(trash)) Directory.CreateDirectory(trash);
            //copyFiles("C:\\googleCode\\revup\\", "C:\\Dev\\app\\revup\\");
            //copyFiles("C:\\test\\", ".\\");
            if (args.Length < 2 || args[0].Length < 1 || args[0].Length < 1)
            {
                Console.WriteLine("revup: errore di sintassi");
                Console.WriteLine("Utilizzo: revup \"destination dir\" \"search dir\"");
                Console.WriteLine("Esempio: revup \"c:\\\" \".\"");
                //pause();
                return;
            }
            string a1 = args[0].TrimEnd('\\') + "\\";
            string a2 = args[1].TrimEnd('\\') + "\\";
            cmdLine[0] = args[0];
            cmdLine[1] = args[1];
            copyFiles(args[0], args[1]);
            //pause();
        }

        static void log(string msg)
        {
            if (!sessionStarted)
            {
                flog.WriteLine("-------------------------------------------------------");
                flog.Flush();
                flog.WriteLine("NUOVA SESSIONE: da " + cmdLine[1] + " a " + cmdLine[0]);
                flog.Flush();
                sessionStarted = true;
            }
            DateTime d = DateTime.Now;
            flog.WriteLine(d + " - " + msg);
            flog.Flush();
        }

        //static void readConfig(string confile)
        //{
        //    FileStream f = new FileStream("revup.conf", FileMode.OpenOrCreate);
        //}

        static void sesionStart()
        {
        }

        static string[] ignoreFiles(string dir)
        {
            Stack<string> ret = new Stack<string>();
            try
            {
                StreamReader sr = new StreamReader(dir + ".svn/dir-prop-base");
                string line;
                int currentRev;
                int startRev;
                bool b_start = false;

                while (!sr.EndOfStream)
                {
                    line = sr.ReadLine();
                    if (line.Length > 2)
                    {
                        if (!b_start)
                        {
                            if (line.Substring(0, 2) == "K ")
                            {
                                currentRev = int.Parse(line.Substring(2));
                            }
                            else if (line == "svn:ignore")
                            {
                                b_start = true;
                            }
                        }
                        else
                        {
                            if (line.Substring(0, 2) == "V ")
                            {
                                startRev = int.Parse(line.Substring(2));
                            }
                            else if (line == "END")
                            {
                                break;
                            }
                            else
                            {
                                ret.Push(line);
                            }
                        }
                    }
                }
            }
            catch (FileNotFoundException)
            { }

            return ret.ToArray();
        }

        static void removeFile(FileInfo[] ar, string name)
        {
            for (int i = 0; i < ar.Length; i++)
            {
                if (ar[i] != null && ar[i].Name == name)
                    ar[i] = null;
            }
        }

        static void removeDir(DirectoryInfo[] ar,string name)
        {
            for (int i = 0; i < ar.Length; i++)
            {
                if (ar[i] != null && ar[i].Name == name)
                    ar[i] = null;
            }
        }

        static void deleteFiles(FileInfo[] ar)
        {
            for (int i = 0; i < ar.Length; i++)
            {
                if (ar[i] != null)
                {
                    log("delete file " + ar[i].FullName);
                    Console.WriteLine("delete file " + ar[i].FullName);
                    ar[i].CopyTo(trash + ar[i].Name, true);
                    ar[i].Delete();
                }
            }
        }

        static void deleteDirs(DirectoryInfo[] ar)
        {
            for (int i = 0; i < ar.Length; i++)
            {
                if (ar[i] != null)
                {
                    log("delete dir " + ar[i].FullName);
                    Console.WriteLine("delete dir " + ar[i].FullName);
                    if (Directory.Exists(trash + ar[i].Name)) Directory.Delete(trash + ar[i].Name);
                    ar[i].MoveTo(trash + ar[i].Name);
                }
            }
        }

        static void copyFile(FileInfo f, string destDir)
        {
            Console.Write("Copia: " + destDir + f.Name + " ...");
            f.CopyTo(destDir + f.Name, true);
            Console.WriteLine("ok");
            log("Copia: " + destDir + f.Name);
        }

        static void copyFiles(string destDir, string currentDir)
        {
            DirectoryInfo curdir = new DirectoryInfo(currentDir);
            DirectoryInfo destdir = new DirectoryInfo(destDir);
            FileInfo[] files = curdir.GetFiles();
            FileInfo[] removefiles = destdir.GetFiles();
            DirectoryInfo[] removedirs = destdir.GetDirectories();
            DirectoryInfo[] dirs = curdir.GetDirectories();
            string[] ign = ignoreFiles(currentDir);

            // ignora la cartella ".svn" della destinazione
            removeDir(removedirs, ".svn");

            foreach (FileInfo fi in files)
            {
                FileInfo fdest = new FileInfo(destDir + fi.Name);

                if (!ign.Contains<string>(fi.Name))
                {
                    if ((!fdest.Exists || fdest.LastWriteTime < fi.LastWriteTime))
                        copyFile(fi, destDir);
                    removeFile(removefiles, fi.Name);
                }
            }

            foreach (DirectoryInfo di in dirs)
            {
                if (di.Name != ".svn" && !ign.Contains<string>(di.Name))
                {
                    if (!Directory.Exists(destDir + di.Name))
                    {
                        try
                        {
                            Directory.CreateDirectory(destDir + di.Name);
                            Console.WriteLine("Crea cartella: " + destDir + di.Name);
                            log("Crea cartella: " + destDir + di.Name);
                        }
                        catch (IOException e)
                        {
                            Console.WriteLine("Impossibile creare la cartella: " + destDir + di.Name);
                            log("Impossibile creare la cartella: " + destDir + di.Name);
                            continue;
                        }
                    }
                    removeDir(removedirs, di.Name);
                    copyFiles(destDir + di.Name + "\\", currentDir + di.Name + "\\");
                }
            }
 
            deleteFiles(removefiles);
            deleteDirs(removedirs);
       }

        static void pause()
        {
            Console.Write("Premere un tasto per chiudere...");
            Console.ReadKey();
        }
    }
}
